package com.fzhucc.modules.expert.service.impl;

import com.fzhucc.exception.BadRequestException;
import com.fzhucc.modules.expert.domain.Expert;
import com.fzhucc.modules.expert.domain.ExpertOfflineConfig;
import com.fzhucc.modules.expert.domain.dto.*;
import com.fzhucc.modules.expert.repository.ExpertOfflineConfigRepository;
import com.fzhucc.modules.expert.repository.ExpertRepository;
import com.fzhucc.modules.expert.service.ExpertOfflineConfigService;
import com.fzhucc.modules.expert.service.mapstruct.ExpertOfflineConfigMapper;
import com.fzhucc.utils.FileUtil;
import com.fzhucc.utils.PageUtil;
import com.fzhucc.utils.QueryHelp;
import com.fzhucc.utils.ValidationUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
 * @author yyg
 * @description 服务实现
 * @date 2023-10-20
 **/
@Service
@RequiredArgsConstructor
public class ExpertOfflineConfigServiceImpl implements ExpertOfflineConfigService {

    private final ExpertOfflineConfigRepository expertOfflineConfigRepository;
    private final ExpertOfflineConfigMapper expertOfflineConfigMapper;

    private final ExpertRepository expertRepository;

    @Override
    public Map<String, Object> queryAll(ExpertOfflineConfigQueryCriteria criteria, Pageable pageable) {
        criteria.setIsDelete(0);
        Page<ExpertOfflineConfig> page = expertOfflineConfigRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        return PageUtil.toPage(page.map(expertOfflineConfigMapper::toDto));
    }

    @Override
    public List<ExpertOfflineConfigDto> queryAll(ExpertOfflineConfigQueryCriteria criteria) {
        criteria.setIsDelete(0);
        return expertOfflineConfigMapper.toDto(expertOfflineConfigRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
    }

    @Override
    @Transactional
    public ExpertOfflineConfigDto findById(Integer id) {
        ExpertOfflineConfig expertOfflineConfig = expertOfflineConfigRepository.findById(id).orElseGet(ExpertOfflineConfig::new);
        ValidationUtil.isNull(expertOfflineConfig.getId(), "ExpertOfflineConfig", "id", id);
        return expertOfflineConfigMapper.toDto(expertOfflineConfig);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ExpertOfflineConfig> create(ExpertOfflineConfigAddDto dto) {
        List<ExpertOfflineConfig> result = new ArrayList<ExpertOfflineConfig>();
        Integer expertId = dto.getExpertId();
        Optional<Expert> res = expertRepository.findById(expertId);
        if (!res.isPresent()) {
            throw new BadRequestException("专家未找到");
        }
        List<ExpertConfigLists2Dto> list = dto.getList();
        if (list != null && list.size() > 0) {
            for (ExpertConfigLists2Dto dto2 : list) {
                String day = dto2.getDay();
                String address = dto2.getAddress();
                List<String> list1 = dto2.getList();
                Integer limitsCount = dto2.getLimitsCount();
                if (list1 != null && list1.size() > 0) {
                    if (list1.size() == 2) {
                        ExpertOfflineConfig expertOfflineConfig = new ExpertOfflineConfig();
                        expertOfflineConfig.setExpertId(expertId);
                        expertOfflineConfig.setTimeSlot(list1.get(0) + ";" + list1.get(1));
                        expertOfflineConfig.setIsDelete(0);
                        expertOfflineConfig.setAddress(address);
                        expertOfflineConfig.setDay(day);
                        expertOfflineConfig.setLimitsCount(limitsCount);
                        ExpertOfflineConfig save = expertOfflineConfigRepository.save(expertOfflineConfig);
                        result.add(save);
                    }
                }
            }
        }

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ExpertOfflineConfigDto edit(ExpertOfflineConfigEditDto resources) {
        //return expertOfflineConfigMapper.toDto(expertOfflineConfigRepository.save(resources));
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(ExpertOfflineConfig resources) {
        ExpertOfflineConfig expertOfflineConfig = expertOfflineConfigRepository.findById(resources.getId()).orElseGet(ExpertOfflineConfig::new);
        ValidationUtil.isNull(expertOfflineConfig.getId(), "ExpertOfflineConfig", "id", resources.getId());
        expertOfflineConfig.copy(resources);
        expertOfflineConfigRepository.save(expertOfflineConfig);
    }

    @Override
    public void deleteAll(Integer[] ids) {
        /*for (Integer id : ids) {
            expertOfflineConfigRepository.deleteById(id);
        }*/
        for (Integer id : ids) {
            Optional<ExpertOfflineConfig> res = expertOfflineConfigRepository.findById(id);
            if (res.isPresent()) {
                ExpertOfflineConfig expertOfflineConfig = res.get();
                expertOfflineConfig.setIsDelete(1);
                expertOfflineConfigRepository.save(expertOfflineConfig);
            }
        }
    }

    @Override
    public void download(List<ExpertOfflineConfigDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (ExpertOfflineConfigDto expertOfflineConfig : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("专家id", expertOfflineConfig.getExpertId());
            map.put("日期", expertOfflineConfig.getDay());
            map.put("地址", expertOfflineConfig.getAddress());
            map.put("限制人数 最多多少人报名", expertOfflineConfig.getLimitsCount());
            map.put("时间段", expertOfflineConfig.getTimeSlot());
            //map.put("是否h5 小程序展示 默认展示", expertOfflineConfig.getIsShow());
            //map.put("排序", expertOfflineConfig.getSort());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ExpertOfflineConfig> saveList(ExpertOfflineConfigEditDto dto) {
        List<ExpertOfflineConfig> result = new ArrayList<ExpertOfflineConfig>();
        List<Integer> ids = new ArrayList<Integer>();//存所有新增及编辑的ids
        List<Integer> idAlls = new ArrayList<Integer>();
        Integer expertId = dto.getExpertId();
        Optional<Expert> res = expertRepository.findById(expertId);
        if (!res.isPresent()) {
            throw new BadRequestException("专家未找到");
        }
        List<ExpertConfigLists2Dto> list = dto.getList();
        if (list != null && list.size() > 0) {
            for (ExpertConfigLists2Dto expertConfigLists2Dto : list) {
                Integer id = expertConfigLists2Dto.getId();
                List<String> list1 = expertConfigLists2Dto.getList();
                String address = expertConfigLists2Dto.getAddress();
                String day = expertConfigLists2Dto.getDay();
                Integer limitsCount = expertConfigLists2Dto.getLimitsCount();
                //TODO 如果此id为空则表示新增
                if (id == null) {
                    ExpertOfflineConfig expertOfflineConfig = new ExpertOfflineConfig();
                    expertOfflineConfig.setIsDelete(0);
                    expertOfflineConfig.setDay(day);
                    expertOfflineConfig.setLimitsCount(limitsCount);
                    expertOfflineConfig.setAddress(address);
                    expertOfflineConfig.setExpertId(expertId);
                    if (list1.size() == 2) {
                        expertOfflineConfig.setTimeSlot(list1.get(0) + ";" + list1.get(1));
                    }
                    ExpertOfflineConfig save = expertOfflineConfigRepository.save(expertOfflineConfig);
                    ids.add(save.getId());
                    result.add(save);
                } else {
                    Optional<ExpertOfflineConfig> ops = expertOfflineConfigRepository.findById(id);
                    if (ops.isPresent()) {
                        //TODO 有的话编辑 没有的话继续新增 id填此id
                        ExpertOfflineConfig expertOfflineConfig = ops.get();
                        expertOfflineConfig.setTimeSlot(list1.get(0) + ";" + list1.get(1));
                        expertOfflineConfig.setExpertId(expertId);
                        expertOfflineConfig.setIsDelete(0);
                        expertOfflineConfig.setDay(day);
                        expertOfflineConfig.setLimitsCount(limitsCount);
                        expertOfflineConfig.setAddress(address);
                        ExpertOfflineConfig save = expertOfflineConfigRepository.save(expertOfflineConfig);
                        ids.add(save.getId());
                        result.add(save);
                    } else {
                        ExpertOfflineConfig expertOfflineConfig = new ExpertOfflineConfig();
                        expertOfflineConfig.setTimeSlot(list1.get(0) + ";" + list1.get(1));
                        expertOfflineConfig.setExpertId(expertId);
                        expertOfflineConfig.setId(id);
                        expertOfflineConfig.setIsDelete(0);
                        expertOfflineConfig.setDay(day);
                        expertOfflineConfig.setLimitsCount(limitsCount);
                        expertOfflineConfig.setAddress(address);
                        ExpertOfflineConfig save = expertOfflineConfigRepository.save(expertOfflineConfig);
                        ids.add(save.getId());
                        result.add(save);
                    }
                }
            }
            List<ExpertOfflineConfig> resList = expertOfflineConfigRepository.findByExpertId(expertId);
            if (resList != null && resList.size() > 0) {
                for (ExpertOfflineConfig expertOfflineConfig : resList) {
                    idAlls.add(expertOfflineConfig.getId());
                }
                if (idAlls.size() > ids.size()) {
                    //TODO 多余的全部设为删除状态
                    List<Integer> differenceSet = getDifferenceSet(idAlls, ids);
                    if (differenceSet != null && differenceSet.size() > 0) {
                        for (Integer id : differenceSet) {
                            Optional<ExpertOfflineConfig> res2 = expertOfflineConfigRepository.findById(id);
                            if (res2.isPresent()) {
                                ExpertOfflineConfig expertOfflineConfig = res2.get();
                                expertOfflineConfig.setIsDelete(1);
                                expertOfflineConfigRepository.save(expertOfflineConfig);
                            }
                        }
                    }
                }
            }
        } else {
            //TODO则删除原有时间段配置
            List<ExpertOfflineConfig> resList = expertOfflineConfigRepository.findByExpertId(expertId);
            if (resList != null && resList.size() > 0) {
                for (ExpertOfflineConfig expertOfflineConfig : resList) {
                    Integer id = expertOfflineConfig.getId();
                    Optional<ExpertOfflineConfig> res2 = expertOfflineConfigRepository.findById(id);
                    if (res2.isPresent()) {
                        ExpertOfflineConfig expertOfflineConfig2 = res2.get();
                        expertOfflineConfig2.setIsDelete(1);
                        expertOfflineConfigRepository.save(expertOfflineConfig2);
                    }
                }
            }
        }
        return result;
    }

    public List<Integer> getDifferenceSet(List<Integer> allList, List<Integer> list) {
        List<Integer> resultList = new ArrayList<>();
        Map<String, Integer> map = new HashMap<>();
        list.forEach(i2 -> {
            map.put(i2 + "", i2);
        });
        allList.forEach(i1 -> {
            Integer m = map.get(i1 + "");
            //如果为空，则证明list2中无该数据
            if (m == null) {
                resultList.add(i1);
            }
        });
        return resultList;
    }
}